// TODO：数据发生变化时进行中转
import Dep from './Dep'
import parsePath from './parsePath'

let uid = 0
export default class Watcher {
    // 监听对象，表达式，回调函数
    constructor(target, expression, callback) {
        this.id = uid++
        this.target = target
        this.getter = parsePath(expression)     // 获取取值函数
        this.callback = callback
        this.value = this.get()
    }
    // TODO：更新依赖
    update () {
        this.run()
    }
    // TODO：
    run () {
        this.getAndInvoke(this.callback)
    }
    // TODO：得到值并且唤起方法
    getAndInvoke (callback) {
        // 这里不应该再执行依赖收集的 get函数 了
        const value = this.getter(this.target)
        // 执行订阅函数
        if (value !== this.value || typeof value == 'object') {
            const oldValue = this.value
            this.value = value
            // 模仿Vue中监听函数：传入一个 新值和旧值
            callback.call(this.target, value, oldValue)
        }
    }
    // TODO：依赖收集
    get () {
        // 进入依赖收集阶段，让全局的 Dep.target 设置为 Watcher本身
        Dep.target = this
        // 获取对象
        const obj = this.target
        // 获取值
        let value
        // 防止中途出现错误
        try {
            value = this.getter(obj)
        }
        finally {
            Dep.target = null
        }
        return value
    }
}